﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Web;
using System.Web.Caching;

namespace RBAC.SqlCache
{
    internal partial class CacheFather<T> : RBAC.SqlCache.ICacheOperator<T>
    {
        #region 成员方法

        RBAC.IDAL.IBasicOperation<T> dal;
        RemoveCaches removeCaches;
        string[] tablesName;
        string tableName;
        public CacheFather(string tablename, RBAC.IDAL.IBasicOperation<T> newDal, params string[] tablesName)
        {
            dal = newDal;
            removeCaches = new RemoveCaches(tablename + "_");
            this.tablesName = tablesName;
            this.tableName = tablename;
        }

        #endregion

        #region ICacheFather<T> 成员

        ///// <summary> 增加一条数据
        ///// </summary>
        int ICacheOperator<T>.Add(T model)
        {
            int data = dal.Add(model);
            if (Caches.EnableCache && data != 0)
            {
                RemoveList();
            }
            return data;
        }

        ///// <summary>增加多条数据
        ///// </summary>
        void ICacheOperator<T>.Add(IList<T> m)
        {
            foreach (T model in m)
                dal.Add(model);

            if (Caches.EnableCache)
            {
                RemoveList();
            }
        }

        /// <summary>删除多条数据
        /// </summary>
        bool ICacheOperator<T>.Delete(List<int> Id, out int mistakeId)
        {
            mistakeId = -1;
            if (Caches.EnableCache)
            {
                #region
                RemoveOtherModelCache();
                foreach (int i in Id)
                {
                    if (!dal.Delete(i))
                    {
                        mistakeId = i;
                        return false;
                    }
                    else
                    {
                        removeCaches.RemoveModelCache(i);
                    }
                }
                return true;
                #endregion
            }
            else
            {
                foreach (int i in Id)
                {
                    if (!dal.Delete(i))
                    {
                        mistakeId = i;
                        return false;
                    }
                }
                return true;
            }
        }

        /// <summary>删除一条数据
        /// </summary>
        bool ICacheOperator<T>.Delete(int Id)
        {
            bool b = dal.Delete(Id);
            if (Caches.EnableCache && b)
            {
                removeCaches.RemoveModelCache(Id);
                RemoveOtherModelCache();
            }
            return b;
        }

        /// <summary>获得全部的列表
        /// </summary>
        /// <returns></returns>
        DataSet ICacheOperator<T>.GetAllList(string strSql)
        {
            if (Caches.EnableCache)
            {
                string key = removeCaches.ListAddKey(strSql);
                if (HttpRuntime.Cache[key] != null)
                {
                    return (DataSet)HttpRuntime.Cache[key];
                }
                else
                {
                    DataSet ds = dal.GetList(strSql,null);
                    CacheAdd(key, ds);
                    return ds;
                }
            }
            else
            {
                return dal.GetList(strSql, null);
            }
        }

       /* /// <summary>返回分页的数据
        /// </summary>
        /// <param name="fldName"></param>
        /// <param name="tblName"></param>
        /// <param name="Condition"></param>
        /// <param name="orderBy"></param>
        /// <param name="pageSize"></param>
        /// <param name="currentIndex"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        DataTable ICacheOperator<T>.GetDataTable(string fldName, string tblName, string Condition, string orderBy, int pageSize, int currentIndex, ref int count)
        {
            if (Caches.EnableCache)                    //启用缓存
            {
                string key = fldName + tblName + Condition + orderBy + pageSize.ToString() + currentIndex.ToString() + count.ToString();
                string listKey = removeCaches.ListAddKey(key);
                string countKey = removeCaches.CountAddKey(key);
                if (HttpRuntime.Cache[listKey] != null && HttpRuntime.Cache[countKey] != null)
                {
                    count = (int)HttpRuntime.Cache[countKey];
                    return (DataTable)HttpRuntime.Cache[key];
                }
                else
                {
                    DataTable dt = dal.GetDataTable(fldName, tblName, Condition, orderBy, pageSize, currentIndex, ref count);
                    CacheAdd(listKey, dt);
                    CacheAdd(countKey, count);
                    return dt;
                }
            }
            else                                               //直接调用
            {
                return dal.GetDataTable(fldName, tblName, Condition, orderBy, pageSize, currentIndex, ref count);
            }

        }*/
        /// <summary>
        /// 获取DataSet分页数据集
        /// </summary>
        /// <param name="PageSize"></param>
        /// <param name="PageIndex"></param>
        /// <param name="strWhere"></param>
        /// <param name="OrderFiled"></param>
        /// <param name="OrderBy"></param>
        /// <param name="RecordCount"></param>
        /// <returns></returns>
        public DataSet GetPageList(int PageSize, int PageIndex, string strWhere, string OrderFiled, string OrderBy, out int RecordCount)
        {
            if (Caches.EnableCache)
            {
                string key = tableName + PageSize + PageIndex + strWhere + OrderFiled + OrderBy;
                string listKey = removeCaches.ListAddKey(key);
                string countKey = removeCaches.CountAddKey(key);
                if (HttpRuntime.Cache[listKey] != null && HttpRuntime.Cache[countKey] != null)
                {
                    RecordCount = (int)HttpRuntime.Cache[countKey];
                    return (DataSet)HttpRuntime.Cache[key];
                }
                else
                {
                    DataSet ds = dal.GetList(PageSize,PageIndex,strWhere,OrderFiled,OrderBy);
                    RecordCount = dal.GetRecordCount(strWhere);
                    CacheAdd(listKey,ds);
                    CacheAdd(countKey,RecordCount);
                    return ds;
                }
            }
            else
            {
                DataSet ds = dal.GetList(PageSize, PageIndex, strWhere, OrderFiled, OrderBy);
                RecordCount = dal.GetRecordCount(strWhere);
                return ds;
            }
        }

        public IList<T> GetPageIList(int PageSize, int PageIndex, string strWhere, string OrderFiled, string OrderBy, out int RecordCount)
        {
            if (Caches.EnableCache)
            {
                string key = tableName + PageSize + PageIndex + strWhere + OrderFiled + OrderBy;
                string listKey = removeCaches.ListAddKey(key);
                string countKey = removeCaches.CountAddKey(key);
                if (HttpRuntime.Cache[listKey] != null && HttpRuntime.Cache[countKey] != null)
                {
                    RecordCount = (int)HttpRuntime.Cache[countKey];
                    return (IList<T>)HttpRuntime.Cache[key];
                }
                else
                {
                    IList<T> list = dal.GetIList(PageSize, PageIndex, strWhere, OrderFiled, OrderBy);
                    RecordCount = dal.GetRecordCount(strWhere);
                    CacheAdd(listKey, list);
                    CacheAdd(countKey, RecordCount);
                    return list;
                }
            }
            else
            {
                IList<T> list = dal.GetIList(PageSize, PageIndex, strWhere, OrderFiled, OrderBy);
                RecordCount = dal.GetRecordCount(strWhere);
                return list;
            }
        }

        /// <summary>获得一个实体
        /// </summary>
        /// <param name="id">主键</param>
        /// <returns></returns>
        T ICacheOperator<T>.GetModel(int id)
        {
            if (Caches.EnableCache)
            {
                string key = removeCaches.basicKey + "Model_" + id.ToString();
                if (HttpRuntime.Cache[key] != null)
                {
                    return (T)HttpRuntime.Cache[key];
                }
                else
                {
                    T model = dal.GetModel(id);
                    CacheAdd(key, model);
                    return model;
                }
            }
            else
            {
                return dal.GetModel(id);
            }
        }

        /// <summary>更新一条数据
        /// </summary>
        bool ICacheOperator<T>.Update(T model, int id)
        {
            bool b = dal.Update(model);
            if (Caches.EnableCache && b)
            {
                RemoveUpdataOperateCache(id);
            }
            return b;
        }

        /// <summary>根据SQL语句更新数据 不推荐使用
        /// </summary>
        /// <param name="id"></param>
        /// <param name="strSql"></param>
        /// <param name="sqlParams"></param>
        /// <returns></returns>
        bool ICacheOperator<T>.Update(int id, string strSql, SqlParameter[] sqlParams)
        {
            bool b = dal.Update(strSql, sqlParams);
            if (Caches.EnableCache && b)
            {
                RemoveUpdataOperateCache(id);
            }
            return b;

        }

        /// <summary>更新多条数据
        /// </summary>
        bool ICacheOperator<T>.Update(List<int> ids, string strSql, SqlParameter[] sqlParams, out int mistakeId)
        {
            int paramsId = 0;
            mistakeId = -1;
            bool blnJudge = false;

            if (Caches.EnableCache)    //启用缓存的操作
            {
                #region
                RemoveOtherModelCache();
                foreach (int i in ids)
                {
                    blnJudge = dal.Update(strSql, sqlParams[paramsId]);
                    if (!blnJudge)
                    {
                        removeCaches.RemoveModelCache(i);
                        paramsId++;

                    }
                    else
                    {
                        mistakeId = i;
                        break;
                    }
                }
                #endregion
            }
            else                           //不启用缓存的操作
            {
                foreach (int i in ids)
                {
                    blnJudge = dal.Update(strSql, sqlParams[paramsId]);
                    if (!blnJudge)
                    {
                        mistakeId = i;
                        break;
                    }
                    else
                    {
                        paramsId++;
                    }
                }
            }
            return blnJudge;
        }

        #endregion

        #region 辅助方法

        /// <summary>删除列表缓存
        /// </summary>
        private void RemoveList()
        {
            removeCaches.RemoveListCache();
            removeCaches.RemoveCountCache();
            RemoveOtherCache(tablesName);
        }

        /// <summary>删除其他的缓存表
        /// </summary>
        /// <param name="s"></param>
        private void RemoveOtherCache(params string[] tableNames)
        {
            foreach (string tableName in tableNames)
            {
                removeCaches.RemoveAll(tableName);
            }
        }

        /// <summary>单条更新操作的缓存清除
        /// </summary>
        /// <param name="id"></param>
        private void RemoveUpdataOperateCache(int id)
        {
            removeCaches.RemoveModelCache(id);
            RemoveList();
        }

        /// <summary>删除除Model外的所有本表缓存
        /// </summary>
        private void RemoveOtherModelCache()
        {
            RemoveList();
        }

        /// <summary>缓存的添加
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        private void CacheAdd(string key, object value)
        {
            Caches.TryAddCache(key, value, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
        }

        #endregion
    }
}
